using Admin.NET.Core;
using Admin.NET.Core.Service;
using AspNetCoreRateLimit;
using Furion;
using Furion.SpecificationDocument;
using Furion.VirtualFileServer;
using IGeekFan.AspNetCore.Knife4jUI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OnceMi.AspNetCore.OSS;
using System;
using System.IO;
using System.Net;
using System.Net.Mail;
using Yitter.IdGenerator;

namespace Admin.NET.Web.Core;

public class Startup : AppStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 配置选项
        services.AddProjectOptions();
        // 缓存注册
        services.AddCache();
        // SqlSugar
        services.AddSqlSugar();
        // JWT
        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
        // 允许跨域
        services.AddCorsAccessor();
        // 远程请求
        services.AddRemoteRequest();
        // 任务队列
        services.AddTaskQueue();
        // 任务调度
        services.AddSchedule(options =>
        {
            options.AddPersistence<DbJobPersistence>(); // 添加作业持久化器
        });
        // 脱敏检测
        services.AddSensitiveDetection();
        // 控制台格式化
        services.AddConsoleFormatter(options =>
        {
            options.DateFormat = "yyyy-MM-dd HH:mm:ss(zzz) dddd";
        });
        // 日志监听
        services.AddMonitorLogging(options =>
        {
            options.IgnorePropertyNames = new[] { "Byte" };
            options.IgnorePropertyTypes = new[] { typeof(byte[]) };
        });

        services.AddControllersWithViews()
            .AddAppLocalization()
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 首字母小写（驼峰样式）
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
                // options.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
                // options.SerializerSettings.DateParseHandling = DateParseHandling.None;
                // options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal });
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用
                // options.SerializerSettings.Converters.AddLongTypeConverters(); // long转string（防止js精度溢出） 超过16位开启
                // options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; // 忽略空值
            })
            //.AddXmlSerializerFormatters()
            //.AddXmlDataContractSerializerFormatters()
            .AddInjectWithUnifyResult<AdminResultProvider>();

        //// 第三方授权登录
        //services.AddAuthentication()
        //    .AddWeixin(options =>
        //    {
        //        var opt = App.GetOptions<OAuthOptions>();
        //        options.ClientId = opt.Weixin.ClientId;
        //        options.ClientSecret = opt.Weixin.ClientSecret;
        //    });

        // ElasticSearch
        services.AddElasticSearch();

        // 配置Nginx转发获取客户端真实IP
        // 注1：如果负载均衡不是在本机通过 Loopback 地址转发请求的，一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
        // 注2：如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True，则不需要下面的配置代码
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.All;
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });

        // 限流服务
        services.AddInMemoryRateLimiting();
        services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

        // 事件总线
        services.AddEventBus(options =>
        {
            options.UseUtcTimestamp = false;
            // 不启用事件日志
            options.LogEnabled = false;
            // 事件执行器（失败重试）
            options.AddExecutor<RetryEventHandlerExecutor>();
            //// 替换事件源存储器
            //options.ReplaceStorer(serviceProvider =>
            //{
            //    var redisClient = serviceProvider.GetService<ICache>();
            //    return new RedisEventSourceStorer(redisClient);
            //});
        });

        // OSS对象存储（必须一个个赋值）
        var ossOpt = App.GetOptions<OSSProviderOptions>();
        services.AddOSSService(Enum.GetName(ossOpt.Provider), options =>
        {
            options.Provider = ossOpt.Provider;
            options.Endpoint = ossOpt.Endpoint;
            options.AccessKey = ossOpt.AccessKey;
            options.SecretKey = ossOpt.SecretKey;
            options.Region = ossOpt.Region;
            options.IsEnableCache = ossOpt.IsEnableCache;
            options.IsEnableHttps = ossOpt.IsEnableHttps;
        });

        // 电子邮件
        var emailOpt = App.GetOptions<EmailOptions>();
        services.AddFluentEmail(emailOpt.DefaultFromEmail, emailOpt.DefaultFromName)
            .AddSmtpSender(new SmtpClient(emailOpt.Host, emailOpt.Port)
            {
                EnableSsl = emailOpt.EnableSsl,
                UseDefaultCredentials = emailOpt.UseDefaultCredentials,
                Credentials = new NetworkCredential(emailOpt.UserName, emailOpt.Password)
            });

        // 模板引擎
        services.AddViewEngine();

        // 即时通讯
        services.AddSignalR(options =>
            {
                options.KeepAliveInterval = TimeSpan.FromSeconds(5);
            })
            .AddJsonProtocol();

        // logo显示
        services.AddLogoDisplay();

        // 日志记录
        if (App.GetConfig<bool>("Logging:File:Enabled")) // 日志写入文件
        {
            Array.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>
            {
                services.AddFileLogging(options =>
                {
                    options.WithStackFrame = true; // 显示堆栈信息
                    options.FileNameRule = fileName => string.Format(fileName, DateTime.Now, logLevel.ToString()); // 每天创建一个文件
                    options.WriteFilter = logMsg => logMsg.LogLevel == logLevel; // 日志级别
                    options.HandleWriteError = (writeError) => // 写入失败时启用备用文件
                    {
                        writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));
                    };
                });
            });
        }
        if (App.GetConfig<bool>("Logging:Database:Enabled")) // 日志写入数据库
        {
            services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
            {
                options.WithStackFrame = true; // 显示堆栈信息
                options.WithTraceId = true; // 显示线程Id
                options.IgnoreReferenceLoop = false; // 忽略循环检测
                options.WriteFilter = (logMsg) =>
                {
                    return logMsg.LogName == "System.Logging.LoggingMonitor"; // 只写LoggingMonitor日志
                };
            });
        }
        if (App.GetConfig<bool>("Logging:ElasticSearch:Enabled")) // 日志写入ElasticSearch
        {
            services.AddDatabaseLogging<ElasticSearchLoggingWriter>(options =>
            {
                options.WithStackFrame = true; // 显示堆栈信息
                options.WithTraceId = true; // 显示线程Id
                options.IgnoreReferenceLoop = false; // 忽略循环检测
                options.MessageFormat = LoggerFormatter.Json;
                options.WriteFilter = (logMsg) =>
                {
                    return logMsg.LogName == "System.Logging.LoggingMonitor"; // 只写LoggingMonitor日志
                };
            });
        }

        // 雪花Id
        YitIdHelper.SetIdGenerator(App.GetOptions<SnowIdOptions>());

        // 验证码
        services.AddLazyCaptcha();


        // 如果你需要其他SPA服务，比如React的热模块替换（HMR）
        //services.AddSpaStaticFiles(configuration =>
        //{
        //  //  configuration.RootPath = "pages";
           
          
        //});
        
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        #region  整个原来的

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseForwardedHeaders();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseForwardedHeaders();
            app.UseHsts();
        }

        // 添加状态码拦截中间件
        app.UseUnifyResultStatusCodes();

        // 配置多语言
        app.UseAppLocalization();

        //// 启用HTTPS
        app.UseHttpsRedirection();

        // 特定文件类型（文件后缀）处理
        var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
        // contentTypeProvider.Mappings[".文件后缀"] = "MIME 类型";
        app.UseStaticFiles(new StaticFileOptions
        {
            ContentTypeProvider = contentTypeProvider
        });

        app.UseRouting();

        app.UseCorsAccessor();

        // 限流组件（在跨域之后）
        app.UseIpRateLimiting();
        app.UseClientRateLimiting();

        app.UseAuthentication();
        app.UseAuthorization();

        // 任务调度看板
        app.UseScheduleUI();

        // 配置Swagger-Knife4UI（路由前缀一致代表独立，不同则代表共存）
        app.UseKnife4UI(options =>
        {
            options.RoutePrefix = "api";
            foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
            {
                options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
            }
        });

        app.UseInject(string.Empty);

        app.UseEndpoints(endpoints =>
        {
            // 注册集线器
            endpoints.MapHubs();

            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });

        #endregion


       // if (env.IsDevelopment())
       // {
       //     app.UseDeveloperExceptionPage();
       //     app.UseForwardedHeaders();
       // }
       // else
       // {
       //     app.UseExceptionHandler("/Home/Error");
       //     app.UseForwardedHeaders();
       //     app.UseHsts();
       // }

       // // 添加状态码拦截中间件
       // app.UseUnifyResultStatusCodes();

       // // 配置多语言
       // app.UseAppLocalization();

       // //// 启用HTTPS
       // app.UseHttpsRedirection();

       // // 特定文件类型（文件后缀）处理
       //// var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
       // //contentTypeProvider.Mappings[".文件后缀"] = "MIME 类型";
       // //app.UseStaticFiles(new StaticFileOptions
       // //{
       // //    ContentTypeProvider = contentTypeProvider
       // //});



       // app.UseCorsAccessor();

       // // 限流组件（在跨域之后）
       // app.UseIpRateLimiting();
       // app.UseClientRateLimiting();

       // app.UseAuthentication();
       // app.UseAuthorization();

       // // 任务调度看板
       // app.UseScheduleUI();

       // // 配置Swagger-Knife4UI（路由前缀一致代表独立，不同则代表共存）
       // app.UseKnife4UI(options =>
       // {
       //     options.RoutePrefix = "kapi";
       //     foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
       //     {
       //         options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
       //     }
       // });

       // app.UseInject(string.Empty);

       // #region 自己写
       // //var adminIndexFilePath = Path.Combine(env.ContentRootPath, "pages", "index.html");
       // ////app.UseSpaStaticFiles(new StaticFileOptions
       // ////{
       // ////    FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "pages")),
       // ////    RequestPath = "" // 空字符串表示根路径
       // ////});

       // //var provider = new FileExtensionContentTypeProvider();
       // //provider.Mappings[".html"] = "text/html";

       // //app.UseSpaStaticFiles(new StaticFileOptions
       // //{
       // //    ContentTypeProvider = provider
       // //});

       // ////app.UseEndpoints(endpoints =>
       // ////{
       // ////    // 例如，API的路由
       // ////    endpoints.MapControllers();
       // ////});

       // //app.UseSpa(spa =>
       // //{
       // //    spa.Options.SourcePath = "pages"; // 确保这里的路径正确指向前端项目的构建输出目录
       // //    //if (env.IsDevelopment())
       // //    //{
       // //    //    spa.UseReactDevelopmentServer(url: "http://localhost:3000"); // 如果是React，并且在开发模式下
       // //    //}
       // //});

       // ////  app.UseStaticFiles();
       // //app.UseRouting();


       // //设置默认起始页（如default.html）
       // //此处的路径是相对于wwwroot文件夹的相对路径
       // //var defaultFilesOptions = new DefaultFilesOptions();
       // //defaultFilesOptions.DefaultFileNames.Clear();
       // //defaultFilesOptions.DefaultFileNames.Add("index.html");
       // //app.UseDefaultFiles(defaultFilesOptions);
       // //    app.UseStaticFiles();


       // //var fileProvider = new PhysicalFileProvider(Path.Combine(env.WebRootPath, "AdminApp", "dist"));
       // //app.UseSpaStaticFiles(new StaticFileOptions { FileProvider = fileProvider });

       // //app.UseSpa(spa =>
       // //{
       // //    spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions
       // //    {
       // //        OnPrepareResponse = fileCtx =>
       // //        {
       // //            fileCtx.Context.Response.Headers.Remove("cache-control");
       // //            fileCtx.Context.Response.Headers.Add(
       // //                "cache-control",
       // //                "no-store, no-cache, must-revalidate");
       // //        },
       // //        FileProvider = fileProvider
       // //    };
       // //});



       // #endregion

       // #region 最简单的写法，没用 都不能访问了
       // //app.UseRouting();

       // //app.UseEndpoints(endpoints =>
       // //{
       // //    endpoints.MapControllers();
       // //});


       // #endregion


       // #region 根据域名分配不同的处理逻辑


       
     

       // // var fileProvider = new PhysicalFileProvider(Path.Combine(env.WebRootPath, "AdminApp", "dist"));

       // // app.MapWhen(context => context.Request.Host.Value.Contains("hxhcarcoloradmin."), adminApp =>
       // // {
       // //     adminApp.UseSpaStaticFiles(new StaticFileOptions { FileProvider = fileProvider });

       // //     adminApp.UseSpa(spa =>
       // //     {
       // //         spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions
       // //         {
       // //             OnPrepareResponse = fileCtx =>
       // //             {
       // //                 fileCtx.Context.Response.Headers.Remove("cache-control");
       // //                 fileCtx.Context.Response.Headers.Add(
       // //                     "cache-control",
       // //                     "no-store, no-cache, must-revalidate");
       // //             },
       // //             FileProvider = fileProvider
       // //         };
       // //     });
       // // });

       // //app.MapWhen(context => context.Request.Host.Value.Contains("hxhcarcolorapi."), apiApp =>
       // //{
       // //    apiApp.UseRouting();
       // //    // API 路由映射
       // //    apiApp.UseEndpoints(endpoints =>
       // //    {
       // //        endpoints.MapHubs();
       // //        endpoints.MapControllers(); // 假设你使用的是MVC风格的API控制器
       // //    });
       // //});

       // #endregion


       // #region 原来的
       // //原来的
       // app.UseRouting();
       // app.UseEndpoints(endpoints =>
       // {
       //     // 注册集线器
       //     endpoints.MapHubs();

       //     endpoints.MapControllerRoute(
       //         name: "default",
       //         pattern: "{controller=Home}/{action=Index}/{id?}");
       // });
       // #endregion

       // #region 星期一百度的

       // //var fileProvider = new PhysicalFileProvider(Path.Combine(Environment.CurrentDirectory, "pages"));


       // //app.UseStaticFiles(new StaticFileOptions { FileProvider = fileProvider });
       // //app.UseSpaStaticFiles(new StaticFileOptions { FileProvider = fileProvider });
       // //app.UseRouting();
       // //// 这段代码确保所有的请求都会返回index.html，由前端路由处理
       // //app.MapWhen(x => x.Request.Host.Value.Contains("hxhcarcoloradmin.yokfilm.com"), builder =>
       // //{
       // //    builder.Use(async (context, next) =>
       // //    {
       // //        context.Response.ContentType = "text/html";
       // //        await context.Response.SendFileAsync(context.Request.PathBase + "/index.html");
       // //    });
       // //});

       // //// 添加MVC或控制器路由
       // //app.UseEndpoints(endpoints =>
       // //{
       // //    endpoints.MapControllerRoute(
       // //        name: "default",
       // //        pattern: "{controller=Home}/{action=Index}/{id?}");
       // //});

       // //// 使用SPA
       // //app.UseSpa(spa =>
       // //{
       // //    spa.Options.SourcePath = "pages";
       // //    spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions
       // //    {
       // //        //OnPrepareResponse = fileCtx =>
       // //        //{
       // //        //    fileCtx.Context.Response.Headers.Remove("cache-control");
       // //        //    fileCtx.Context.Response.Headers.Add(
       // //        //        "cache-control",
       // //        //        "no-store, no-cache, must-revalidate");
       // //        //},
       // //        FileProvider = fileProvider
       // //    };

       // //    //if (env.IsDevelopment())
       // //    //{
       // //    //    spa.UseReactDevelopmentServer(npmScript: "start");
       // //    //}
       // //});

       // #endregion

       // #region  百度ai
       // //  // 获取admin SPA的index.html文件的物理路径
       // //  var adminIndexFilePath = Path.Combine(env.ContentRootPath, "pages", "index.html");


       // //  // 使用MapWhen根据域名来分支
       // //app.MapWhen(context => context.Request.Host.Value.Contains("hxhcarcoloradmin.yokfilm.com"), adminApp =>
       // ////  app.MapWhen(context => context.Request.Path.Value.Contains("123"), adminApp =>
       // //{
       // //    // 在这个分支中配置admin SPA的静态文件和路由

       // //    // 提供admin SPA的静态文件
       // //    adminApp.UseStaticFiles(new StaticFileOptions
       // //      {
       // //          FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "pages")),
       // //          //   FileProvider = new PhysicalFileProvider(Path.Combine(env.WebRootPath, "pages")),
       // //          RequestPath = ""
       // //      });




       // //      // 对于所有其他请求，返回admin的index.html文件
       // //      adminApp.Use(async (context, next) =>
       // //      {
       // //          // 如果请求的不是静态文件（比如图片、JS、CSS等），则返回index.html
       // //          if (!Path.HasExtension(context.Request.Path.Value))
       // //          {

       // //              context.Response.ContentType = "text/html";
       // //              await context.Response.SendFileAsync(adminIndexFilePath);
       // //          }
       // //          else
       // //          {
       // //              // 对于静态文件请求，继续处理管道中的下一个中间件
       // //              await next.Invoke();
       // //          }
       // //      });

       // //      // 注意：这里不需要再调用UseEndpoints或UseSpa，因为我们已经手动处理了SPA的路由
       // //  });

       // //  // ... 其他配置，比如常规的SPA或MVC路由 ...

       // //  // 如果你有其他SPA或常规的MVC应用，它们应该配置在上面的MapWhen之后
       // //  // app.UseSpa(...); 或 app.UseEndpoints(...);

       // #endregion
    }
}